import cv2
import numpy as np
import requests
import json
import re
import os
import base64
from config import *

class FurnitureOcr:
    def __init__(self):
        self.match_table = {
            '卧室A': '主卧_1000',
            '卧室B': '次卧_1000',
            '卧室C': '其他卧_1000',
            '卧室D': '其他卧_1000',
            '客厅': '客厅_1001',
            '客厅A': '客厅_1001',
            '客厅B': '客厅_1001',
            '卫生间': '卫生间_1002', 
            '卫生间A': '卫生间_1002', 
            '卫生间B': '卫生间_1002',
            '卫生间C': '卫生间_1002',
            '厨房': '厨房_1002',
            '储': '储物间_1000',
            '阳台A': '阳台_1003', 
            '阳台B': '阳台_1003',
            '阳台C': '阳台_1003',
        }

    def download_image(self):
        try:
            response = requests.get(self.url)
            response.raise_for_status()  # Raise HTTPError for bad response status
            image_array = np.asarray(bytearray(response.content), dtype=np.uint8)
            image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
            if image is None:
                raise ValueError("Failed to decode image")
            return image
        except requests.exceptions.RequestException as e:
            print(f"Error downloading image from {self.url}: {e}")
            return None
        except Exception as e:
            print(f"Error processing image: {e}")
            return None

    """3.OCR识别"""
    def perform_ocr(self, image):
        temp_image_path = 'temp_image.jpg'
        cv2.imwrite(temp_image_path, image)

        # url = 'https://mis-jiali.517.cn/paddleocr/api/getOcr'
        with open(temp_image_path, 'rb') as file:
            files = {'file': file}
            data = {'Text': 'string'}
            response = requests.post(ocrUrl, files=files, data=data)

        os.remove(temp_image_path)

        if response.status_code == 200:
            try:
                ocr_result = response.json()
                # print(f"OCR结果: {ocr_result}")
                # if "DataBody" in ocr_result:
                #     extracted_values = []
                #     for item in ocr_result["DataBody"]:
                #         for text in item[1]:
                #             if isinstance(text, str):
                #                 # 匹配一个或多个汉字
                #                 chinese_chars = re.findall(r'[\u4e00-\u9fff]+', text)
                #                 if chinese_chars:
                #                     coordinates = item[0]
                #                     extracted_values.append((chinese_chars, coordinates))
                #     return ocr_result, extracted_values
                if "DataBody" in ocr_result:
                    extracted_values = []
                    for item in ocr_result["DataBody"]:
                        for text in item[1]:
                            if isinstance(text, str):
                                if "贝壳找房" in text:
                                    continue  # 跳过包含"贝壳找房"的文本
                                # 匹配包含一个或多个汉字的整个字符串
                                if re.search(r'[\u4e00-\u9fff]+', text):
                                    coordinates = item[0]
                                    #json格式
                                    # extracted_values.append((text, coordinates))
                                    #这个格式的[{'name': '厨房', 'point': [[281.0, 53.0], [328.0, 53.0], [328.0, 79.0], [281.0, 79.0]]}]
                                    # name_point = {"name": text, "point": coordinates}
                                    # center_x = (coordinates[0][0] + coordinates[2][0]) / 2
                                    # center_y = (coordinates[0][1] + coordinates[2][1]) / 2
                                    #取整有小数
                                    # center_x = int((coordinates[0][0] + coordinates[1][0]) / 2)
                                    # center_y = int((coordinates[0][1] + coordinates[3][1]) / 2)
                                    # 取文字块的右下角坐标
                                    center_x = coordinates[2][0]
                                    center_y = coordinates[2][1]
                                    extracted_values.append({"name": text, "point": [center_x, center_y]})                                    
                                    # print(extracted_values)
                    return extracted_values               
                else:
                    return "响应中不包含DataBody", None
            except json.JSONDecodeError:
                return "响应内容不是有效的JSON格式", None
        else:
            return f"请求失败，状态码: {response.status_code}", None

    def process_image(self, image):
        original_width = image.shape[1]
        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        lower_white = np.array([200, 200, 200])
        upper_white = np.array([255, 255, 255])
        white_mask = cv2.inRange(image, lower_white, upper_white)

        lower_black = np.array([0, 0, 0])
        upper_black = np.array([50, 50, 50])
        black_mask = cv2.inRange(image, lower_black, upper_black)

        kernel = np.ones((5, 5), np.uint8)
        white_mask = cv2.morphologyEx(white_mask, cv2.MORPH_OPEN, kernel)
        white_mask = cv2.morphologyEx(white_mask, cv2.MORPH_CLOSE, kernel)
        black_mask = cv2.morphologyEx(black_mask, cv2.MORPH_OPEN, kernel)
        black_mask = cv2.morphologyEx(black_mask, cv2.MORPH_CLOSE, kernel)
        
        # contours_image = image.copy()
        wall_contours, _ = cv2.findContours(black_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # cv2.drawContours(contours_image, wall_contours, -1, (0, 255, 0), 1)
        # cv2.imshow('Contours on Black Mask', contours_image)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        #以前150现在改成400，大图问题
        MIN_CONTOUR_AREA = 400
        filtered_wall_contours = [cnt for cnt in wall_contours if cv2.contourArea(cnt) > MIN_CONTOUR_AREA]
        x, y, w, h = cv2.boundingRect(np.concatenate(filtered_wall_contours))
        # xmin = x
        # xmax = x + w
        # ymin = y
        # ymax = y + h
        # max_min = str((xmin, ymin, xmax, ymax))

        cropped_image = image[y:y+h, x:x+w]
        cropped_width = cropped_image.shape[1]
        width_ratio = original_width / cropped_width
        # 进行OCR识别
        extracted_values = self.perform_ocr(cropped_image)
        
        # 替换房间名称
        new_extracted_values = []
        for room in extracted_values:
            original_name = room['name']
            if original_name in self.match_table:
                replacement = self.match_table[original_name]
                if isinstance(replacement, list):
                    room['name'] = replacement.pop(0)
                else:
                    room['name'] = replacement
                pass                
                new_extracted_values.append(room)

        return new_extracted_values, original_width, width_ratio   

    """5.gradio接口返回这些需要的字段"""
    # def process_urls(self, url):
    #     self.url = url
    #     image = self.download_image()
    #     if image is None:
    #         raise ValueError("Failed to download or process the image")
    #     extracted_values= self.process_image(image)
    #     return extracted_values
    def process_urls(self, url, img_radio, move_xy, orgimg_data, radio_wall_result,alldata_result):
        self.url = url
        image = self.download_image()
        if image is None:
            raise ValueError("Failed to download or process the image")
        
        extracted_values, original_width, width_ratio = self.process_image(image)
        
        for item in extracted_values:
            item['point'] = [int(coord * img_radio) for coord in item['point']]
            item['point'] = [int(coord * radio_wall_result) for coord in item['point']]
            item['point'] = [item['point'][0] + move_xy[2][0], item['point'][1] + move_xy[2][0]]
            item['point'] = [item['point'][0] - move_xy[0], item['point'][1] - move_xy[1]]
        # 坐标翻转
        extracted_values = self.xy_data_turn(orgimg_data,extracted_values,radio_wall_result)
        
        
        
        return extracted_values
    """6.图片转换"""
    def image_to_base64(self, image):
        _, buffer = cv2.imencode('.jpg', image)
        img_base64 = base64.b64encode(buffer).decode('utf-8')
        return img_base64

    def xy_data_turn(self, orgimg_data, extracted_values,radio_wall_result):
        x_min, y_min, x_max, y_max = orgimg_data

        diff = y_max*radio_wall_result - y_min*radio_wall_result
        # diff_dev = (diff / 2)+y_min

        for i,item in enumerate(extracted_values):
            y_point = y_max - item["point"][1] + y_min
            extracted_values[i]["point"][1] = y_point
      
        return extracted_values

    def xy_data_turn_wall(self, alldata_result):
        x_data = []
        y_data = []
        for i,bbox in  enumerate(alldata_result):
            # 如果 x1 = x2，将边界框信息加入 x1_equals_x2_bboxes
            index, x1, y1, x2, y2 = bbox
            if x1 == x2:
                x_data.append(bbox)
            
            # 如果 y1 = y2，将边界框信息加入 y1_equals_y2_bboxes
            elif y1 == y2:
                y_data.append(bbox)

                
        x_data_mins = [item[2] for item in x_data]
        x_data_maxs = [item[4] for item in x_data]
        x_datas = []
        x_datas.extend(x_data_mins)
        x_datas.extend(x_data_maxs)
        _min = min(x_datas)
        _max = max(x_datas)
        diff = _max - _min
        diff_dev = (diff / 2)+_min

        # print(f"x_datas:{x_datas},_min:{_min},_max:{_max},diff:{diff},diff_dev:{diff_dev}")
        new_x_data = []
        new_y_data = []
        for item in x_data:
            xx_start = _max - item[2] + _min
            xx_end = _max - item[4] + _min
            # print(f"item[2]:{item[2]},item[4]:{item[4]},xx_start:{xx_start},xx_end:{xx_end}")
            if item[0]==1:
                new_x_data.append((item[0], item[1], xx_end, item[3], xx_start, item[5]))
            else:
                new_x_data.append((item[0], item[1], xx_end, item[3], xx_start))
        # print(x_data)
        # print(new_x_data)

        for item in y_data:
            xx_start = _max - item[2] + _min
            xx_end = _max - item[4] + _min
            # print(f"item[2]:{item[2]},item[4]:{item[4]},xx_start:{xx_start},xx_end:{xx_end}")
            if item[0]==1:
                new_y_data.append((item[0], item[1], xx_end, item[3], xx_start, item[5]))
            else:
                new_y_data.append((item[0], item[1], xx_end, item[3], xx_start))
        return new_x_data, new_y_data

# # Example usage
# url = 'https://ke-image.ljcdn.com/hdic-frame/standard_477d6cbd-9d4f-42cf-b819-4082813fc63a.png.1440x1080.jpg?from=ke.com'
# furnitureocr = FurnitureOcr()
# extracted_values = furnitureocr.process_urls(url)
# # print(f"ocr_result: {ocr_result}")
# print(f"extracted_values: {extracted_values}")
